#!/bin/sh

# Copyright (c) 2013, 2021, Oracle and/or its affiliates.
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2.0,
# as published by the Free Software Foundation.
#
# This program is also distributed with certain software (including
# but not limited to OpenSSL) that is licensed under separate terms,
# as designated in a particular file or component or in included license
# documentation.  The authors of MySQL hereby grant you an additional
# permission to link the program and your derivative works with the
# separately licensed software that they have included with MySQL.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License, version 2.0, for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA


sourcedir=@PROJECT_SOURCE_DIR@
builddir=@PROJECT_BINARY_DIR@
installdir=@CMAKE_INSTALL_PREFIX@

# Install Trees:
bindir=@INSTALL_BINDIR@
libexecdir=@INSTALL_SBINDIR@
libdir=@INSTALL_LIBDIR@
scriptsdir=@INSTALL_SCRIPTDIR@
sharedir=@INSTALL_MYSQLSHAREDIR@
memcachedbin=@MEMCACHED_BIN_PATH@

SOURCE_DIR=$sourcedir
BUILD_DIR=$builddir
INSTALL_DIR=$installdir

MYSELF=`who am i | awk '{print $1}'`
WORKING_DIR=`pwd`

if test -w $WORKING_DIR 
 then
   HOME_BASE=$WORKING_DIR
 else
   HOME_BASE=$HOME 
fi

# In an in-source build, BUILD_DIR = SOURCE_DIR.
# Try BUILD_DIR first.  If it does not exist, we assume this is an install,
# so we use INSTALL_DIR.
if test -d $BUILD_DIR
 then
  # Use build dir
  MEMCACHED_DIR=$BUILD_DIR/storage/ndb/memcache/extra/memcached
  MGM_CLIENT_DIR=$BUILD_DIR/storage/ndb/src/mgmclient
  MGM_SERVER_DIR=$BUILD_DIR/storage/ndb/src/mgmsrv
  NDBD_DIR=$BUILD_DIR/storage/ndb/src/kernel
  MYSQL_CLIENT_DIR=$BUILD_DIR/client
  MYSQL_SERVER_DIR=$BUILD_DIR/scripts
  ENGINE_SO_DIR=$BUILD_DIR/storage/ndb/memcache
  METADATA_DIR=$BUILD_DIR/scripts/
  SCRIPTS_DIR=$INSTALL_DIR/$scriptsdir    # See NOTE below
 else
  # Use install dir
  MEMCACHED_DIR=`dirname $memcachedbin`
  MGM_CLIENT_DIR=$INSTALL_DIR/$libexecdir
  MGM_SERVER_DIR=$INSTALL_DIR/$libexecdir
  NDBD_DIR=$INSTALL_DIR/$libexecdir
  MYSQL_CLIENT_DIR=$INSTALL_DIR/$bindir
  MYSQL_SERVER_DIR=$INSTALL_DIR/$libexecdir
  ENGINE_SO_DIR=$INSTALL_DIR/$libdir
  METADATA_DIR=$sharedir/memcache-api
  SCRIPTS_DIR=$INSTALL_DIR/$scriptsdir
fi

## NOTE.
##  mysql_install_db only works from an installed copy.
##  mtr fixes this by reimplementing mysql_install_db internally.
##  Our solution for now is to hope we find a copy in the install_dir
 
test_paths() {
  test_exec_path $MGM_CLIENT_DIR ndb_mgm
  test_exec_path $MGM_SERVER_DIR ndb_mgmd
  test_exec_path $MYSQL_CLIENT_DIR mysql
  test_exec_path $MYSQL_CLIENT_DIR mysqladmin
  test_exec_path $MYSQL_SERVER_DIR mysqld_safe
  test_exec_path $NDBD_DIR ndbd
  test_exec_path $MEMCACHED_DIR memcached
  test_exec_path $SCRIPTS_DIR mysql_install_db
  test_read_path $ENGINE_SO_DIR ndb_engine.so
  test_read_path $METADATA_DIR ndb_memcache_metadata.sql
}

test_exec_path() {
  if [ ! -x $1/$2 ] 
   then
    echo "Fatal error: cannot execute $2 at $1"
    exit
  fi
}

test_read_path() {
  if [ ! -r $1/$2 ] 
   then
    echo "Fatal error: cannot read $2 at $1"
    exit
  fi
}

build_dirs() {
  echo Creating sandbox
  mkdir $HOME_BASE/sandbox
  mkdir $HOME_BASE/sandbox/data
  mkdir $HOME_BASE/sandbox/ndb 
  mkdir $HOME_BASE/sandbox/ndb-config
}

write_my_cnf() {
  ( echo "[mysqld]"
    echo "ndbcluster"
    echo "datadir=$HOME_BASE/sandbox/data"
    echo "pid-file=$HOME_BASE/sandbox/mysqld.pid"
    echo "user=$MYSELF"
    echo "innodb_log_file_size=1M"
    echo
  ) > $HOME_BASE/sandbox/my.cnf
 }

write_cluster_ini() {
  ( echo "[MGM]"
    echo "NodeId=1"
    echo "datadir=$HOME_BASE/sandbox/ndb"
    echo "hostname=localhost"
    echo 
    echo "[DB DEFAULT]"
    echo "NoOfReplicas=1"
    echo "TimeBetweenGlobalCheckpoints=12000"
    echo "DataMemory=180M"
    echo "IndexMemory=60M"
    echo "HeartbeatIntervalDbApi=15000"
    echo
    echo "[NDBD]"
    echo "NodeId=2"
    echo "datadir=$HOME_BASE/sandbox/ndb"
    echo 
    echo "[API]"
    echo "[API]"
    echo "[API]"
    echo "[API]"
    echo "[API]"
    echo "[API]"
    echo "[API]"
  ) > $HOME_BASE/sandbox/cluster.ini
}

do_install_db() {
  if test `uname` = "Darwin"
    then OUTFILE=`mktemp XXXXXX`
    else OUTFILE=`mktemp`
  fi
  $SCRIPTS_DIR/mysql_install_db \
    --basedir=$INSTALL_DIR --datadir=$HOME_BASE/sandbox/data \
    --skip-name-resolve --user=$MYSELF > $OUTFILE
  if test ! -d $HOME_BASE/sandbox/data/mysql 
    then echo "Failed: mysql_install_db did not work:"
    cat $OUTFILE
    rm $OUTFILE
    exit    
    else echo "Created MySQL System Tables"
    rm $OUTFILE
  fi
}

wait_for_mysql_ready() {
  while ! $MYSQL_CLIENT_DIR/mysqladmin -s ping 
    do
      sleep 1
      echo waiting
  done
}


start_mgm_server() {
  INITIAL="--initial"
  test -f $HOME_BASE/sandbox/ndb-config/ndb_1_config.bin.1 && INITIAL=""

  $MGM_SERVER_DIR/ndb_mgmd -f $HOME_BASE/sandbox/cluster.ini \
    --config-dir=$HOME_BASE/sandbox/ndb-config $INITIAL
    
  sleep 5
}

start_ndbd() {
  $NDBD_DIR/ndbd 
  sleep 5
}

start_mysql_server() {
  $MYSQL_SERVER_DIR/mysqld_safe --defaults-file=$HOME_BASE/sandbox/my.cnf &
  sleep 3
  wait_for_mysql_ready
}

mysqld_is_running() {  
   test_pid mysqld.pid
}

mgm_server_is_running() {  
   test_pid ndb/ndb_1.pid
}

ndbd_is_running()  {  
   test_pid ndb/ndb_2.pid
}

memcached_is_running() {
   test_pid memcached.pid
}

test_pid() {
  test -f sandbox/$1  || return 1
  SERVERPID=`cat $HOME_BASE/sandbox/$1`
  ps -p "$SERVERPID" > /dev/null || return 1
  return 0
}

load_metadata() {
  echo Loading NDB Memcache configuration data
  DDL_SCRIPT=$METADATA_DIR/ndb_memcache_metadata.sql
  $MYSQL_CLIENT_DIR/mysql --connect-timeout=10 -u root < $DDL_SCRIPT || TRY_AGAIN=1
  test "$TRY_AGAIN" = "1" && $MYSQL_CLIENT_DIR/mysql --connect-timeout=10 \
    -u root < $DDL_SCRIPT
}

start_memcached() {
    $MEMCACHED_DIR/memcached -d -v \
    -P $HOME_BASE/sandbox/memcached.pid \
    -E $ENGINE_SO_DIR/ndb_engine.so $1 $2
}

stop_memcached() {
  SERVERPID=`cat $HOME_BASE/sandbox/memcached.pid`
  test -n "$SERVERPID" && kill $SERVERPID
}

stop_mysqld() {
  $MYSQL_CLIENT_DIR/mysqladmin -u root shutdown
}

stop_mgm_server() {
  $MGM_CLIENT_DIR/ndb_mgm -e shutdown
}

final_message() {
  sleep 2
  echo
  echo "Sandbox directory is $HOME_BASE/sandbox"
  echo "Memcached is $MEMCACHED_DIR/memcached"
  echo 
  echo "Use \"sh sandbox.sh stop\" to stop memcached & MySQL Cluster"
  echo 
}

usage() {
  echo "sandbox.sh start [ndb_mgmd | ndbd | mysql | memcached]"
  echo "           stop  [ndb_mgmd | mysql | memcached]"
  echo "           status"
  echo
  exit
}

cmd_status() {
  if mgm_server_is_running 
    then echo "[ndb_mgmd]   running"
    else echo "[ndb_mgmd]   stopped"
  fi
  if ndbd_is_running 
    then echo "[ndbd]       running"
    else echo "[ndbd]       stopped"
  fi
  if mysqld_is_running
    then echo "[mysqld]     running"
    else echo "[mysqld]     stopped"
  fi
  if memcached_is_running
    then echo "[memcached]  running"
    else echo "[memcached]  stopped"
  fi
}

cmd_stop() {
  test "$1" = "memcached"  &&   stop_memcached   &&  exit
  test "$1" = "mysqld"     &&   stop_mysqld      &&  exit
  test "$1" = "ndb_mgmd"   &&   stop_mgm_server  &&  exit

  test "$1" = ""  ||   usage

  # stop all
  mysqld_is_running        &&   stop_mysqld
  memcached_is_running     &&   stop_memcached
  mgm_server_is_running    &&   stop_mgm_server
}  

cmd_start() {
  test "$1" = "memcached"  &&  start_memcached "$2" "$3" && exit
  test "$1" = "mysqld"     &&  start_mysql_server && exit
  test "$1" = "ndbd"       &&  start_ndbd         && exit
  test "$1" = "ndb_mgmd"   &&  start_mgm_server   && exit

  test "$1" = ""  ||   usage
  
  # start all
  test -d sandbox                     ||  build_dirs
  test -f sandbox/my.cnf              ||  write_my_cnf
  test -f sandbox/cluster.ini         ||  write_cluster_ini
  test -d sandbox/data/mysql          ||  do_install_db
  mgm_server_is_running               ||  start_mgm_server
  ndbd_is_running                     ||  start_ndbd 
  mysqld_is_running                   ||  start_mysql_server  
  test -d sandbox/data/ndbmemcache    ||  load_metadata  
  memcached_is_running                ||  start_memcached

  final_message
}  


# ------------------------------ main script --------------------------

( cd $HOME_BASE 
  test_paths
  if test "$1" = "stop" 
   then 
     cmd_stop "$2"
  elif test "$1" = "start"  
   then
     cmd_start "$2" "$3" "$4"
  elif test "$1" = "status" 
    then
     cmd_status
  else 
     usage
  fi
)
